/*
    作者：zx
    时间：2023.2.12
    描述：FAT系统，可参考系统结构zxOS_architecture/文件系统相关
        更具体可见 《FAT32中文白皮书》(强烈建议)
*/

#ifndef FATFS_H
#define FATFS_H

#include "comm/types.h"
#include "ipc/mutex.h"

#define DIRITEM_NAME_FREE       0xE5        // 当前此项空闲
#define DIRITEM_NAME_END        0x00        // 当前此项空闲且之后所有项空闲

#define DIRITEM_ATTR_READ_ONLY  0x1
#define DIRITEM_ATTR_HIDDEN     0x2
#define DIRITEM_ATTR_SYSTEM     0x4
#define DIRITEM_ATTR_VOLUME_ID  0x8
#define DIRITEM_ATTR_DIRECTORY  0x10
#define DIRITEM_ATTR_ARCHIVE    0x20
#define DIRITEM_LONG_NAME       (0x1 | 0x2 | 0x4 | 0x8)

#define CLUSTER_NEXT_FREE 0
#pragma pack(1)
// 根目录区表项
typedef struct _diritem_t
{
    uint8_t DIR_Name[11];                   // 文件名（8+3，8个字节文件名，3个字节扩展名）
    uint8_t DIR_Attr;                       // 属性
    uint8_t DIR_NTRes;                      // 保留位
    uint8_t DIR_CrtTimeTeenth;              // 创建时间的毫秒
    uint16_t DIR_CrtTime;                   // 创建时间
    uint16_t DIR_CrtDate;                   // 创建日期
    uint16_t DIR_LastAccDate;               // 最后访问日期
    uint16_t DIR_FstClusHI;                 // 簇号高16位
    uint16_t DIR_WrtTime;                   // 修改时间
    uint16_t DIR_WrtDate;                   // 修改时期
    uint16_t DIR_FstClusL0;                 // 簇号低16位
    uint32_t DIR_FileSize;                  // 文件字节大小
}diritem_t;

// dbr结构，读取文件系统信息
typedef struct _dbr_t{
    uint8_t BS_jmpBoot[3];                  // 跳转指令，指向启动代码
    uint8_t BS_OEMName[8];                  // 建议设为默认值“MSWIN4.1”
    uint16_t BPB_BytsPerSec;                // 扇区大小,512字节
    uint8_t BPB_SecPerClus;                 // 簇包含的扇区数
    uint16_t BPB_RsvdSecCnt;                // 保留区扇区数量（包含FAT表前所有扇区）
    uint8_t BPB_NumFATs;                    // FAT表数量，一般为2
    uint16_t BPB_RootEntCnt;                // 根目录表表项数（包含FAT表前所有扇区）
    uint16_t TotSec16;                      // 总扇区数
    uint8_t BPB_Media;                      // 媒体类型
    uint16_t BPB_FATSz16;                   // FAT表所占扇区数
    uint16_t BPB_SecPerTrk;                 // 每磁道扇区数
    uint16_t BPB_NumHeads;                  // 磁头数
    uint32_t BPB_HiddSec;                   // 隐藏扇区数
    uint32_t BPB_TotSec32;                  // 总的扇区数

	uint8_t BS_DrvNum;                      // 磁盘驱动器参数
	uint8_t BS_Reserved1;				    // 保留字节
	uint8_t BS_BootSig;                     // 扩展引导标记
	uint32_t BS_VolID;                      // 卷标序号
	uint8_t BS_VolLab[11];                  // 磁盘卷标
	uint8_t BS_FileSysType[8];              // 文件类型名称
}dbr_t;
#pragma()

typedef struct _fat_t
{
    uint32_t table_start;       
    uint32_t table_count;       // 表长度
    uint32_t table_sectors;     // 表所占扇区数

    uint32_t bytes_per_sector;
    uint32_t sector_per_clus;   // 每簇扇区数   

    uint32_t root_start;        // 根目录区开始扇区数
    uint32_t root_ent_count;    // 根目录区项数
    uint32_t data_start;        // 数据区开始扇区数
    uint32_t bytes_per_clus;    // 簇的字节数

    int curr_sector;            // 当前缓冲区保存的是哪个扇区的数据
    uint8_t * fat_buffer;       // 缓存区，保存上次读取的扇区数据，防止重复读取同一磁盘
    struct _fs_t * fs;
    mutex_t mutex;
}fat_t;

typedef uint16_t cluster_t;
#define FAT_CLUSTER_INVALID 0xFFF8
#endif // !FATFS_H